home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / tar-1_11.lha / tar-1.11.2 / create.c < prev    next >
C/C++ Source or Header  |  1993-03-25  |  34KB  |  1,455 lines

  1. /* Create a tar archive.
  2.    Copyright (C) 1985, 1992, 1993 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Create a tar archive.
  22.  *
  23.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  24.  */
  25.  
  26. #ifdef _AIX
  27.  #pragma alloca
  28. #endif
  29. #include <sys/types.h>
  30. #include <stdio.h>
  31. #include <errno.h>
  32. #ifndef STDC_HEADERS
  33. extern int errno;
  34. #endif
  35.  
  36. #ifdef BSD42
  37. #include <sys/file.h>
  38. #else
  39. #ifndef V7
  40. #include <fcntl.h>
  41. #endif
  42. #endif
  43.  
  44. #include "tar.h"
  45. #include "port.h"
  46.  
  47. #ifndef    __MSDOS__
  48. #include <pwd.h>
  49. #include <grp.h>
  50. #endif
  51.  
  52. #if defined (_POSIX_VERSION)
  53. #include <utime.h>
  54. #else
  55. struct utimbuf
  56. {
  57.   long actime;
  58.   long modtime;
  59. };
  60.  
  61. #endif
  62.  
  63. extern struct stat hstat;    /* Stat struct corresponding */
  64.  
  65. #ifndef __MSDOS__
  66. extern dev_t ar_dev;
  67. extern ino_t ar_ino;
  68. #endif
  69.  
  70. /* JF */
  71. extern struct name *gnu_list_name;
  72.  
  73. /*
  74.  * If there are no symbolic links, there is no lstat().  Use stat().
  75.  */
  76. #ifndef S_ISLNK
  77. #define lstat stat
  78. #endif
  79.  
  80. extern void print_header ();
  81.  
  82. union record *start_header ();
  83. void blank_name_list ();
  84. int check_exclude ();
  85. PTR ck_malloc ();
  86. PTR ck_realloc ();
  87. void clear_buffer ();
  88. void close_archive ();
  89. void collect_and_sort_names ();
  90. int confirm ();
  91. int deal_with_sparse ();
  92. void find_new_file_size ();
  93. void finish_header ();
  94. int finish_sparse_file ();
  95. void finduname ();
  96. void findgname ();
  97. int is_dot_or_dotdot ();
  98. void open_archive ();
  99. char *name_next ();
  100. void name_close ();
  101. void to_oct ();
  102. void dump_file ();
  103. void write_dir_file ();
  104. void write_eot ();
  105. void write_long ();
  106. int zero_record ();
  107.  
  108. /* This code moved from tar.h since create.c is the only file that cares
  109.    about 'struct link's.  This means that other files might not have to
  110.    include sys/types.h any more. */
  111.  
  112. struct link
  113.   {
  114.     struct link *next;
  115.     dev_t dev;
  116.     ino_t ino;
  117.     short linkcount;
  118.     char name[1];
  119.   };
  120.  
  121. struct link *linklist;        /* Points to first link in list */
  122.  
  123. static nolinks;            /* Gets set if we run out of RAM */
  124.  
  125. /*
  126.  * "Scratch" space to store the information about a sparse file before
  127.  * writing the info into the header or extended header
  128.  */
  129. /* struct sp_array     *sparsearray;*/
  130.  
  131. /* number of elts storable in the sparsearray */
  132. /*int     sparse_array_size = 10;*/
  133.  
  134. void
  135. create_archive ()
  136. {
  137.   register char *p;
  138.   char *name_from_list ();
  139.  
  140.   open_archive (0);        /* Open for writing */
  141.  
  142.   if (f_gnudump)
  143.     {
  144.       char *buf = ck_malloc (PATH_MAX);
  145.       char *q, *bufp;
  146.  
  147.       collect_and_sort_names ();
  148.  
  149.       while (p = name_from_list ())
  150.     dump_file (p, -1, 1);
  151.       /* if(!f_dironly) { */
  152.       blank_name_list ();
  153.       while (p = name_from_list ())
  154.     {
  155.       strcpy (buf, p);
  156.       if (p[strlen (p) - 1] != '/')
  157.         strcat (buf, "/");
  158.       bufp = buf + strlen (buf);
  159.       for (q = gnu_list_name->dir_contents; q && *q; q += strlen (q) + 1)
  160.         {
  161.           if (*q == 'Y')
  162.         {
  163.           strcpy (bufp, q + 1);
  164.           dump_file (buf, -1, 1);
  165.         }
  166.         }
  167.     }
  168.       /* } */
  169.       free (buf);
  170.     }
  171.   else
  172.     {
  173.       while (p = name_next (1))
  174.     dump_file (p, -1, 1);
  175.     }
  176.  
  177.   write_eot ();
  178.   close_archive ();
  179.   if (f_gnudump)
  180.     write_dir_file ();
  181.   name_close ();
  182. }
  183.  
  184. /*
  185.  * Dump a single file.  If it's a directory, recurse.
  186.  * Result is 1 for success, 0 for failure.
  187.  * Sets global "hstat" to stat() output for this file.
  188.  */
  189. void
  190. dump_file (p, curdev, toplevel)
  191.      char *p;            /* File name to dump */
  192.      int curdev;        /* Device our parent dir was on */
  193.      int toplevel;        /* Whether we are a toplevel call */
  194. {
  195.   union record *header;
  196.   char type;
  197.   extern char *save_name;    /* JF for multi-volume support */
  198.   extern long save_totsize;
  199.   extern long save_sizeleft;
  200.   union record *exhdr;
  201.   char save_linkflag;
  202.   extern time_t new_time;
  203.   int critical_error = 0;
  204.   struct utimbuf restore_times;
  205.   /*    int sparse_ind = 0;*/
  206.  
  207.  
  208.   if (f_confirm && !confirm ("add", p))
  209.     return;
  210.  
  211.   /*
  212.      * Use stat if following (rather than dumping) 4.2BSD's
  213.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  214.      * systems, is #define'd to stat anyway.
  215.      */
  216. #ifdef STX_HIDDEN        /* AIX */
  217.   if (0 != f_follow_links ?
  218.       statx (p, &hstat, STATSIZE, STX_HIDDEN) :
  219.       statx (p, &hstat, STATSIZE, STX_HIDDEN | STX_LINK))
  220. #else
  221.   if (0 != f_follow_links ? stat (p, &hstat) : lstat (p, &hstat))
  222. #endif
  223.     {
  224.     badperror:
  225.       msg_perror ("can't add file %s", p);
  226.     badfile:
  227.       if (!f_ignore_failed_read || critical_error)
  228.     errors++;
  229.       return;
  230.     }
  231.  
  232.   restore_times.actime = hstat.st_atime;
  233.   restore_times.modtime = hstat.st_mtime;
  234.  
  235. #ifdef S_ISHIDDEN
  236.   if (S_ISHIDDEN (hstat.st_mode))
  237.     {
  238.       char *new = (char *) alloca (strlen (p) + 2);
  239.       if (new)
  240.     {
  241.       strcpy (new, p);
  242.       strcat (new, "@");
  243.       p = new;
  244.     }
  245.     }
  246. #endif
  247.  
  248.   /* See if we only want new files, and check if this one is too old to
  249.        put in the archive. */
  250.   if (f_new_files
  251.       && !f_gnudump
  252.       && new_time > hstat.st_mtime
  253.       && !S_ISDIR (hstat.st_mode)
  254.       && (f_new_files > 1 || new_time > hstat.st_ctime))
  255.     {
  256.       if (curdev == -1)
  257.     {
  258.       msg ("%s: is unchanged; not dumped", p);
  259.     }
  260.       return;
  261.     }
  262.  
  263. #ifndef __MSDOS__
  264.   /* See if we are trying to dump the archive */
  265.   if (ar_dev && hstat.st_dev == ar_dev && hstat.st_ino == ar_ino)
  266.     {
  267.       msg ("%s is the archive; not dumped", p);
  268.       return;
  269.     }
  270. #endif
  271.   /*
  272.      * Check for multiple links.
  273.      *
  274.      * We maintain a list of all such files that we've written so
  275.      * far.  Any time we see another, we check the list and
  276.      * avoid dumping the data again if we've done it once already.
  277.      */
  278.   if (hstat.st_nlink > 1
  279.       && (S_ISREG (hstat.st_mode)
  280. #ifdef S_ISCTG
  281.       || S_ISCTG (hstat.st_mode)
  282. #endif
  283. #ifdef S_ISCHR
  284.       || S_ISCHR (hstat.st_mode)
  285. #endif
  286. #ifdef S_ISBLK
  287.       || S_ISBLK (hstat.st_mode)
  288. #endif
  289. #ifdef S_ISFIFO
  290.       || S_ISFIFO (hstat.st_mode)
  291. #endif
  292.       ))
  293.     {
  294.       register struct link *lp;
  295.  
  296.       /* First quick and dirty.  Hashing, etc later FIXME */
  297.       for (lp = linklist; lp; lp = lp->next)
  298.     {
  299.       if (lp->ino == hstat.st_ino &&
  300.           lp->dev == hstat.st_dev)
  301.         {
  302.           char *link_name = lp->name;
  303.  
  304.           /* We found a link. */
  305.           while (!f_absolute_paths && *link_name == '/')
  306.         {
  307.           static int link_warn = 0;
  308.  
  309.           if (!link_warn)
  310.             {
  311.               msg ("Removing leading / from absolute links");
  312.               link_warn++;
  313.             }
  314.           link_name++;
  315.         }
  316.           if (link_name - lp->name >= NAMSIZ)
  317.         write_long (link_name, LF_LONGLINK);
  318.           current_link_name = link_name;
  319.  
  320.           hstat.st_size = 0;
  321.           header = start_header (p, &hstat);
  322.           if (header == NULL)
  323.         {
  324.           critical_error = 1;
  325.           goto badfile;
  326.         }
  327.           strncpy (header->header.arch_linkname,
  328.                link_name, NAMSIZ);
  329.  
  330.           /* Force null truncated */
  331.           header->header.arch_linkname[NAMSIZ - 1] = 0;
  332.  
  333.           header->header.linkflag = LF_LINK;
  334.           finish_header (header);
  335.           /* FIXME: Maybe remove from list after all links found? */
  336.           if (f_remove_files)
  337.         {
  338.           if (unlink (p) == -1)
  339.             msg_perror ("cannot remove %s", p);
  340.         }
  341.           return;        /* We dumped it */
  342.         }
  343.     }
  344.  
  345.       /* Not found.  Add it to the list of possible links. */
  346.       lp = (struct link *) ck_malloc ((unsigned) (sizeof (struct link) + strlen (p)));
  347.       if (!lp)
  348.     {
  349.       if (!nolinks)
  350.         {
  351.           msg (
  352.           "no memory for links, they will be dumped as separate files");
  353.           nolinks++;
  354.         }
  355.     }
  356.       lp->ino = hstat.st_ino;
  357.       lp->dev = hstat.st_dev;
  358.       strcpy (lp->name, p);
  359.       lp->next = linklist;
  360.       linklist = lp;
  361.     }
  362.  
  363.   /*
  364.      * This is not a link to a previously dumped file, so dump it.
  365.      */
  366.   if (S_ISREG (hstat.st_mode)
  367. #ifdef S_ISCTG
  368.       || S_ISCTG (hstat.st_mode)
  369. #endif
  370.     )
  371.     {
  372.       int f;            /* File descriptor */
  373.       long bufsize, count;
  374.       long sizeleft;
  375.       register union record *start;
  376.       int header_moved;
  377.       char isextended = 0;
  378.       int upperbound;
  379.       /*        int    end_nulls = 0; */
  380.  
  381.       header_moved = 0;
  382.  
  383. #ifdef BSD42
  384.       if (f_sparse_files)
  385.     {
  386.       /*
  387.           * JK - This is the test for sparseness: whether the
  388.          * "size" of the file matches the number of blocks
  389.          * allocated for it.  If there is a smaller number
  390.          * of blocks that would be necessary to accommodate
  391.          * a file of this size, we have a sparse file, i.e.,
  392.          * at least one of those records in the file is just
  393.          * a useless hole.
  394.          */
  395. #ifdef hpux            /* Nice of HPUX to gratuitiously change it, huh?  - mib */
  396.       if (hstat.st_size - (hstat.st_blocks * 1024) > 1024)
  397. #else
  398.       if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE)
  399. #endif
  400.         {
  401.           int filesize = hstat.st_size;
  402.           register int i;
  403.  
  404.           header = start_header (p, &hstat);
  405.           if (header == NULL)
  406.         {
  407.           critical_error = 1;
  408.           goto badfile;
  409.         }
  410.           header->header.linkflag = LF_SPARSE;
  411.           header_moved++;
  412.  
  413.           /*
  414.              * Call the routine that figures out the
  415.              * layout of the sparse file in question.
  416.              * UPPERBOUND is the index of the last
  417.              * element of the "sparsearray," i.e.,
  418.              * the number of elements it needed to
  419.              * describe the file.
  420.              */
  421.  
  422.           upperbound = deal_with_sparse (p, header);
  423.  
  424.           /*
  425.              * See if we'll need an extended header
  426.              * later
  427.              */
  428.           if (upperbound > SPARSE_IN_HDR - 1)
  429.         header->header.isextended++;
  430.           /*
  431.              * We store the "real" file size so
  432.              * we can show that in case someone wants
  433.              * to list the archive, i.e., tar tvf <file>.
  434.              * It might be kind of disconcerting if the
  435.              * shrunken file size was the one that showed
  436.              * up.
  437.              */
  438.           to_oct ((long) hstat.st_size, 1 + 12,
  439.               header->header.realsize);
  440.  
  441.           /*
  442.              * This will be the new "size" of the
  443.              * file, i.e., the size of the file
  444.              * minus the records of holes that we're
  445.              * skipping over.
  446.              */
  447.  
  448.           find_new_file_size (&filesize, upperbound);
  449.           hstat.st_size = filesize;
  450.           to_oct ((long) filesize, 1 + 12,
  451.               header->header.size);
  452.           /*                to_oct((long) end_nulls, 1+12,
  453.                         header->header.ending_blanks);*/
  454.  
  455.           for (i = 0; i < SPARSE_IN_HDR; i++)
  456.         {
  457.           if (!sparsearray[i].numbytes)
  458.             break;
  459.           to_oct (sparsearray[i].offset, 1 + 12,
  460.               header->header.sp[i].offset);
  461.           to_oct (sparsearray[i].numbytes, 1 + 12,
  462.               header->header.sp[i].numbytes);
  463.         }
  464.  
  465.         }
  466.     }
  467. #else
  468.       upperbound = SPARSE_IN_HDR - 1;
  469. #endif
  470.  
  471.       sizeleft = hstat.st_size;
  472.       /* Don't bother opening empty, world readable files. */
  473.       if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode))
  474.     {
  475.       f = open (p, O_RDONLY | O_BINARY);
  476.       if (f < 0)
  477.         goto badperror;
  478.     }
  479.       else
  480.     {
  481.       f = -1;
  482.     }
  483.  
  484.       /* If the file is sparse, we've already taken care of this */
  485.       if (!header_moved)
  486.     {
  487.       header = start_header (p, &hstat);
  488.       if (header == NULL)
  489.         {
  490.           if (f >= 0)
  491.         (void) close (f);
  492.           critical_error = 1;
  493.           goto badfile;
  494.         }
  495.     }
  496. #ifdef S_ISCTG
  497.       /* Mark contiguous files, if we support them */
  498.       if (f_standard && S_ISCTG (hstat.st_mode))
  499.     {
  500.       header->header.linkflag = LF_CONTIG;
  501.     }
  502. #endif
  503.       isextended = header->header.isextended;
  504.       save_linkflag = header->header.linkflag;
  505.       finish_header (header);
  506.       if (isextended)
  507.     {
  508.       /*            int     sum = 0;*/
  509.       register int i;
  510.       /*            register union record *exhdr;*/
  511.       /*            int     arraybound = SPARSE_EXT_HDR;*/
  512.       /* static */ int index_offset = SPARSE_IN_HDR;
  513.  
  514.     extend:exhdr = findrec ();
  515.  
  516.       if (exhdr == NULL)
  517.         {
  518.           critical_error = 1;
  519.           goto badfile;
  520.         }
  521.       bzero (exhdr->charptr, RECORDSIZE);
  522.       for (i = 0; i < SPARSE_EXT_HDR; i++)
  523.         {
  524.           if (i + index_offset > upperbound)
  525.         break;
  526.           to_oct ((long) sparsearray[i + index_offset].numbytes,
  527.               1 + 12,
  528.               exhdr->ext_hdr.sp[i].numbytes);
  529.           to_oct ((long) sparsearray[i + index_offset].offset,
  530.               1 + 12,
  531.               exhdr->ext_hdr.sp[i].offset);
  532.         }
  533.       userec (exhdr);
  534.       /*            sum += i;
  535.             if (sum < upperbound)
  536.                 goto extend;*/
  537.       if (index_offset + i <= upperbound)
  538.         {
  539.           index_offset += i;
  540.           exhdr->ext_hdr.isextended++;
  541.           goto extend;
  542.         }
  543.  
  544.     }
  545.       if (save_linkflag == LF_SPARSE)
  546.     {
  547.       if (finish_sparse_file (f, &sizeleft, hstat.st_size, p))
  548.         goto padit;
  549.     }
  550.       else
  551.     while (sizeleft > 0)
  552.       {
  553.  
  554.         if (f_multivol)
  555.           {
  556.         save_name = p;
  557.         save_sizeleft = sizeleft;
  558.         save_totsize = hstat.st_size;
  559.           }
  560.         start = findrec ();
  561.  
  562.         bufsize = endofrecs ()->charptr - start->charptr;
  563.  
  564.         if (sizeleft < bufsize)
  565.           {
  566.         /* Last read -- zero out area beyond */
  567.         bufsize = (int) sizeleft;
  568.         count = bufsize % RECORDSIZE;
  569.         if (count)
  570.           bzero (start->charptr + sizeleft,
  571.              (int) (RECORDSIZE - count));
  572.           }
  573.         count = read (f, start->charptr, bufsize);
  574.         if (count < 0)
  575.           {
  576.         msg_perror ("read error at byte %ld, reading\
  577.  %d bytes, in file %s", hstat.st_size - sizeleft, bufsize, p);
  578.         goto padit;
  579.           }
  580.         sizeleft -= count;
  581.  
  582.         /* This is nonportable (the type of userec's arg). */
  583.         userec (start + (count - 1) / RECORDSIZE);
  584.  
  585.         if (count == bufsize)
  586.           continue;
  587.         msg ("file %s shrunk by %d bytes, padding with zeros.", p, sizeleft);
  588.         goto padit;        /* Short read */
  589.       }
  590.  
  591.       if (f_multivol)
  592.     save_name = 0;
  593.  
  594.       if (f >= 0)
  595.     (void) close (f);
  596.  
  597.       if (f_remove_files)
  598.     {
  599.       if (unlink (p) == -1)
  600.         msg_perror ("cannot remove %s", p);
  601.     }
  602.       if (f_atime_preserve)
  603.     utime (p, &restore_times);
  604.       return;
  605.  
  606.       /*
  607.          * File shrunk or gave error, pad out tape to match
  608.          * the size we specified in the header.
  609.          */
  610.     padit:
  611.       while (sizeleft > 0)
  612.     {
  613.       save_sizeleft = sizeleft;
  614.       start = findrec ();
  615.       bzero (start->charptr, RECORDSIZE);
  616.       userec (start);
  617.       sizeleft -= RECORDSIZE;
  618.     }
  619.       if (f_multivol)
  620.     save_name = 0;
  621.       if (f >= 0)
  622.     (void) close (f);
  623.       if (f_atime_preserve)
  624.     utime (p, &restore_times);
  625.       return;
  626.     }
  627.  
  628. #ifdef S_ISLNK
  629.   else if (S_ISLNK (hstat.st_mode))
  630.     {
  631.       int size;
  632.       char *buf = alloca (PATH_MAX + 1);
  633.  
  634.       size = readlink (p, buf, PATH_MAX + 1);
  635.       if (size < 0)
  636.     goto badperror;
  637.       buf[size] = '\0';
  638.       if (size >= NAMSIZ)
  639.     write_long (buf, LF_LONGLINK);
  640.       current_link_name = buf;
  641.  
  642.       hstat.st_size = 0;    /* Force 0 size on symlink */
  643.       header = start_header (p, &hstat);
  644.       if (header == NULL)
  645.     {
  646.       critical_error = 1;
  647.       goto badfile;
  648.     }
  649.       strncpy (header->header.arch_linkname, buf, NAMSIZ);
  650.       header->header.arch_linkname[NAMSIZ - 1] = '\0';
  651.       header->header.linkflag = LF_SYMLINK;
  652.       finish_header (header);    /* Nothing more to do to it */
  653.       if (f_remove_files)
  654.     {
  655.       if (unlink (p) == -1)
  656.         msg_perror ("cannot remove %s", p);
  657.     }
  658.       return;
  659.     }
  660. #endif
  661.  
  662.   else if (S_ISDIR (hstat.st_mode))
  663.     {
  664.       register DIR *dirp;
  665.       register struct dirent *d;
  666.       char *namebuf;
  667.       int buflen;
  668.       register int len;
  669.       int our_device = hstat.st_dev;
  670.  
  671.       /* Build new prototype name */
  672.       len = strlen (p);
  673.       buflen = len + NAMSIZ;
  674.       namebuf = ck_malloc (buflen + 1);
  675.       strncpy (namebuf, p, buflen);
  676.       while (len >= 1 && '/' == namebuf[len - 1])
  677.     len--;            /* Delete trailing slashes */
  678.       namebuf[len++] = '/';    /* Now add exactly one back */
  679.       namebuf[len] = '\0';    /* Make sure null-terminated */
  680.  
  681.       /*
  682.          * Output directory header record with permissions
  683.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  684.          * If old archive format, don't write record at all.
  685.          */
  686.       if (!f_oldarch)
  687.     {
  688.       hstat.st_size = 0;    /* Force 0 size on dir */
  689.       /*
  690.              * If people could really read standard archives,
  691.              * this should be:        (FIXME)
  692.             header = start_header(f_standard? p: namebuf, &hstat);
  693.              * but since they'd interpret LF_DIR records as
  694.              * regular files, we'd better put the / on the name.
  695.              */
  696.       header = start_header (namebuf, &hstat);
  697.       if (header == NULL)
  698.         {
  699.           critical_error = 1;
  700.           goto badfile;    /* eg name too long */
  701.         }
  702.  
  703.       if (f_gnudump)
  704.         header->header.linkflag = LF_DUMPDIR;
  705.       else if (f_standard)
  706.         header->header.linkflag = LF_DIR;
  707.  
  708.       /* If we're gnudumping, we aren't done yet so don't close it. */
  709.       if (!f_gnudump)
  710.         finish_header (header);    /* Done with directory header */
  711.     }
  712.  
  713.       if (f_gnudump)
  714.     {
  715.       int sizeleft;
  716.       int totsize;
  717.       int bufsize;
  718.       union record *start;
  719.       int count;
  720.       char *buf, *p_buf;
  721.  
  722.       buf = gnu_list_name->dir_contents;    /* FOO */
  723.       totsize = 0;
  724.       for (p_buf = buf; p_buf && *p_buf;)
  725.         {
  726.           int tmp;
  727.  
  728.           tmp = strlen (p_buf) + 1;
  729.           totsize += tmp;
  730.           p_buf += tmp;
  731.         }
  732.       totsize++;
  733.       to_oct ((long) totsize, 1 + 12, header->header.size);
  734.       finish_header (header);
  735.       p_buf = buf;
  736.       sizeleft = totsize;
  737.       while (sizeleft > 0)
  738.         {
  739.           if (f_multivol)
  740.         {
  741.           save_name = p;
  742.           save_sizeleft = sizeleft;
  743.           save_totsize = totsize;
  744.         }
  745.           start = findrec ();
  746.           bufsize = endofrecs ()->charptr - start->charptr;
  747.           if (sizeleft < bufsize)
  748.         {
  749.           bufsize = sizeleft;
  750.           count = bufsize % RECORDSIZE;
  751.           if (count)
  752.             bzero (start->charptr + sizeleft, RECORDSIZE - count);
  753.         }
  754.           bcopy (p_buf, start->charptr, bufsize);
  755.           sizeleft -= bufsize;
  756.           p_buf += bufsize;
  757.           userec (start + (bufsize - 1) / RECORDSIZE);
  758.         }
  759.       if (f_multivol)
  760.         save_name = 0;
  761.       if (f_atime_preserve)
  762.         utime (p, &restore_times);
  763.       return;
  764.     }
  765.  
  766.       /* Now output all the files in the directory */
  767. #if 0
  768.       if (f_dironly)
  769.     return;            /* Unless the cmdline said not to */
  770. #endif
  771.       /*
  772.          * See if we are crossing from one file system to another,
  773.          * and avoid doing so if the user only wants to dump one file system.
  774.          */
  775.       if (f_local_filesys && !toplevel && curdev != hstat.st_dev)
  776.     {
  777.       if (f_verbose)
  778.         msg ("%s: is on a different filesystem; not dumped", p);
  779.       return;
  780.     }
  781.  
  782.  
  783.       errno = 0;
  784.       dirp = opendir (p);
  785.       if (!dirp)
  786.     {
  787.       if (errno)
  788.         {
  789.           msg_perror ("can't open directory %s", p);
  790.         }
  791.       else
  792.         {
  793.           msg ("error opening directory %s",
  794.            p);
  795.         }
  796.       return;
  797.     }
  798.  
  799.       /* Hack to remove "./" from the front of all the file names */
  800.       if (len == 2 && namebuf[0] == '.' && namebuf[1] == '/')
  801.     len = 0;
  802.  
  803.       /* Should speed this up by cd-ing into the dir, FIXME */
  804.       while (NULL != (d = readdir (dirp)))
  805.     {
  806.       /* Skip . and .. */
  807.       if (is_dot_or_dotdot (d->d_name))
  808.         continue;
  809.  
  810.       if (NLENGTH (d) + len >= buflen)
  811.         {
  812.           buflen = len + NLENGTH (d);
  813.           namebuf = ck_realloc (namebuf, buflen + 1);
  814.           /* namebuf[len]='\0';
  815.                 msg("file name %s%s too long",
  816.                     namebuf, d->d_name);
  817.                 continue; */
  818.         }
  819.       strcpy (namebuf + len, d->d_name);
  820.       if (f_exclude && check_exclude (namebuf))
  821.         continue;
  822.       dump_file (namebuf, our_device, 0);
  823.     }
  824.  
  825.       closedir (dirp);
  826.       free (namebuf);
  827.       if (f_atime_preserve)
  828.     utime (p, &restore_times);
  829.       return;
  830.     }
  831.  
  832. #ifdef S_ISCHR
  833.   else if (S_ISCHR (hstat.st_mode))
  834.     {
  835.       type = LF_CHR;
  836.     }
  837. #endif
  838.  
  839. #ifdef S_ISBLK
  840.   else if (S_ISBLK (hstat.st_mode))
  841.     {
  842.       type = LF_BLK;
  843.     }
  844. #endif
  845.  
  846.   /* Avoid screwy apollo lossage where S_IFIFO == S_IFSOCK */
  847. #if (_ISP__M68K == 0) && (_ISP__A88K == 0) && defined(S_ISFIFO)
  848.   else if (S_ISFIFO (hstat.st_mode))
  849.     {
  850.       type = LF_FIFO;
  851.     }
  852. #endif
  853.  
  854. #ifdef S_ISSOCK
  855.   else if (S_ISSOCK (hstat.st_mode))
  856.     {
  857.       type = LF_FIFO;
  858.     }
  859. #endif
  860.   else
  861.     goto unknown;
  862.  
  863.   if (!f_standard)
  864.     goto unknown;
  865.  
  866.   hstat.st_size = 0;        /* Force 0 size */
  867.   header = start_header (p, &hstat);
  868.   if (header == NULL)
  869.     {
  870.       critical_error = 1;
  871.       goto badfile;        /* eg name too long */
  872.     }
  873.  
  874.   header->header.linkflag = type;
  875. #if defined(S_IFBLK) || defined(S_IFCHR)
  876.   if (type != LF_FIFO)
  877.     {
  878.       to_oct ((long) major (hstat.st_rdev), 8,
  879.           header->header.devmajor);
  880.       to_oct ((long) minor (hstat.st_rdev), 8,
  881.           header->header.devminor);
  882.     }
  883. #endif
  884.  
  885.   finish_header (header);
  886.   if (f_remove_files)
  887.     {
  888.       if (unlink (p) == -1)
  889.     msg_perror ("cannot remove %s", p);
  890.     }
  891.   return;
  892.  
  893. unknown:
  894.   msg ("%s: Unknown file type; file ignored.", p);
  895. }
  896.  
  897. int
  898. finish_sparse_file (fd, sizeleft, fullsize, name)
  899.      int fd;
  900.      long *sizeleft, fullsize;
  901.      char *name;
  902. {
  903.   union record *start;
  904.   char tempbuf[RECORDSIZE];
  905.   int bufsize, sparse_ind = 0, count;
  906.   long pos;
  907.   long nwritten = 0;
  908.  
  909.  
  910.   while (*sizeleft > 0)
  911.     {
  912.       start = findrec ();
  913.       bzero (start->charptr, RECORDSIZE);
  914.       bufsize = sparsearray[sparse_ind].numbytes;
  915.       if (!bufsize)
  916.     {            /* we blew it, maybe */
  917.       msg ("Wrote %ld of %ld bytes to file %s",
  918.            fullsize - *sizeleft, fullsize, name);
  919.       break;
  920.     }
  921.       pos = lseek (fd, sparsearray[sparse_ind++].offset, 0);
  922.       /*
  923.          * If the number of bytes to be written here exceeds
  924.          * the size of the temporary buffer, do it in steps.
  925.          */
  926.       while (bufsize > RECORDSIZE)
  927.     {
  928.       /*            if (amt_read) {
  929.                 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
  930.                 bufsize -= RECORDSIZE - amt_read;
  931.                 amt_read = 0;
  932.                 userec(start);
  933.                 start = findrec();
  934.                 bzero(start->charptr, RECORDSIZE);
  935.             }*/
  936.       /* store the data */
  937.       count = read (fd, start->charptr, RECORDSIZE);
  938.       if (count < 0)
  939.         {
  940.           msg_perror ("read error at byte %ld, reading %d bytes, in file %s",
  941.               fullsize - *sizeleft, bufsize, name);
  942.           return 1;
  943.         }
  944.       bufsize -= count;
  945.       *sizeleft -= count;
  946.       userec (start);
  947.       nwritten += RECORDSIZE;    /* XXX */
  948.       start = findrec ();
  949.       bzero (start->charptr, RECORDSIZE);
  950.     }
  951.  
  952.  
  953.       clear_buffer (tempbuf);
  954.       count = read (fd, tempbuf, bufsize);
  955.       bcopy (tempbuf, start->charptr, RECORDSIZE);
  956.       if (count < 0)
  957.     {
  958.       msg_perror ("read error at byte %ld, reading %d bytes, in file %s",
  959.               fullsize - *sizeleft, bufsize, name);
  960.       return 1;
  961.     }
  962.       /*        if (amt_read >= RECORDSIZE) {
  963.             amt_read = 0;
  964.             userec(start+(count-1)/RECORDSIZE);
  965.             if (count != bufsize) {
  966.                 msg("file %s shrunk by %d bytes, padding with zeros.", name, sizeleft);
  967.                 return 1;
  968.             }
  969.             start = findrec();
  970.         } else
  971.             amt_read += bufsize;*/
  972.       nwritten += count;    /* XXX */
  973.       *sizeleft -= count;
  974.       userec (start);
  975.  
  976.     }
  977.   free (sparsearray);
  978.   /*    printf ("Amount actually written is (I hope) %d.\n", nwritten); */
  979.   /*    userec(start+(count-1)/RECORDSIZE);*/
  980.   return 0;
  981.  
  982. }
  983.  
  984. void
  985. init_sparsearray ()
  986. {
  987.   register int i;
  988.  
  989.   sp_array_size = 10;
  990.   /*
  991.      * Make room for our scratch space -- initially is 10 elts long
  992.      */
  993.   sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
  994.   for (i = 0; i < sp_array_size; i++)
  995.     {
  996.       sparsearray[i].offset = 0;
  997.       sparsearray[i].numbytes = 0;
  998.     }
  999. }
  1000.  
  1001.  
  1002.  
  1003. /*
  1004.  * Okay, we've got a sparse file on our hands -- now, what we need to do is
  1005.  * make a pass through the file and carefully note where any data is, i.e.,
  1006.  * we want to find how far into the file each instance of data is, and how
  1007.  * many bytes are there.  We store this information in the sparsearray,
  1008.  * which will later be translated into header information.  For now, we use
  1009.  * the sparsearray as convenient storage.
  1010.  *
  1011.  * As a side note, this routine is a mess.  If I could have found a cleaner
  1012.  * way to do it, I would have.  If anyone wants to find a nicer way to do
  1013.  * this, feel free.
  1014.  */
  1015.  
  1016. /* There is little point in trimming small amounts of null data at the */
  1017. /* head and tail of blocks -- it's ok if we only avoid dumping blocks */
  1018. /* of complete null data */
  1019. int
  1020. deal_with_sparse (name, header, nulls_at_end)
  1021.      char *name;
  1022.      union record *header;
  1023.      int nulls_at_end;
  1024. {
  1025.   long numbytes = 0;
  1026.   long offset = 0;
  1027.   /*    long    save_offset;*/
  1028.   int fd;
  1029.   /*    int    current_size = hstat.st_size;*/
  1030.   int sparse_ind = 0, cc;
  1031.   char buf[RECORDSIZE];
  1032. #if 0
  1033.   int read_last_data = 0;    /* did we just read the last record? */
  1034. #endif
  1035.   int amidst_data = 0;
  1036.  
  1037.   header->header.isextended = 0;
  1038.   /*
  1039.      * Can't open the file -- this problem will be caught later on,
  1040.      * so just return.
  1041.      */
  1042.   if ((fd = open (name, O_RDONLY)) < 0)
  1043.     return 0;
  1044.  
  1045.   init_sparsearray ();
  1046.   clear_buffer (buf);
  1047.  
  1048.   while ((cc = read (fd, buf, sizeof buf)) != 0)
  1049.     {
  1050.  
  1051.       if (sparse_ind > sp_array_size - 1)
  1052.     {
  1053.  
  1054.       /*
  1055.          * realloc the scratch area, since we've run out of room --
  1056.          */
  1057.       sparsearray = (struct sp_array *)
  1058.         ck_realloc (sparsearray,
  1059.              2 * sp_array_size * (sizeof (struct sp_array)));
  1060.       sp_array_size *= 2;
  1061.     }
  1062.       if (cc == sizeof buf)
  1063.     {
  1064.       if (zero_record (buf))
  1065.         {
  1066.           if (amidst_data)
  1067.         {
  1068.           sparsearray[sparse_ind++].numbytes
  1069.             = numbytes;
  1070.           amidst_data = 0;
  1071.         }
  1072.         }
  1073.       else
  1074.         {            /* !zero_record(buf) */
  1075.           if (amidst_data)
  1076.         numbytes += cc;
  1077.           else
  1078.         {
  1079.           amidst_data = 1;
  1080.           numbytes = cc;
  1081.           sparsearray[sparse_ind].offset
  1082.             = offset;
  1083.         }
  1084.         }
  1085.     }
  1086.       else if (cc < sizeof buf)
  1087.     {
  1088.       /* This has to be the last bit of the file, so this */
  1089.       /* is somewhat shorter than the above. */
  1090.       if (!zero_record (buf))
  1091.         {
  1092.           if (!amidst_data)
  1093.         {
  1094.           amidst_data = 1;
  1095.           numbytes = cc;
  1096.           sparsearray[sparse_ind].offset
  1097.             = offset;
  1098.         }
  1099.           else
  1100.         numbytes += cc;
  1101.         }
  1102.     }
  1103.       offset += cc;
  1104.       clear_buffer (buf);
  1105.     }
  1106.   if (amidst_data)
  1107.     sparsearray[sparse_ind++].numbytes = numbytes;
  1108.   else
  1109.     {
  1110.       sparsearray[sparse_ind].offset = offset-1;
  1111.       sparsearray[sparse_ind++].numbytes = 1;
  1112.     }
  1113.   close (fd);
  1114.  
  1115.   return sparse_ind - 1;
  1116. }
  1117.  
  1118. /*
  1119.  * Just zeroes out the buffer so we don't confuse ourselves with leftover
  1120.  * data.
  1121.  */
  1122. void
  1123. clear_buffer (buf)
  1124.      char *buf;
  1125. {
  1126.   register int i;
  1127.  
  1128.   for (i = 0; i < RECORDSIZE; i++)
  1129.     buf[i] = '\0';
  1130. }
  1131.  
  1132. #if 0                /* I'm leaving this as a monument to Joy Kendall, who wrote it -mib */
  1133. /*
  1134.  * JK -
  1135.  * This routine takes a character array, and tells where within that array
  1136.  * the data can be found.  It skips over any zeros, and sets the first
  1137.  * non-zero point in the array to be the "start", and continues until it
  1138.  * finds non-data again, which is marked as the "end."  This routine is
  1139.  * mainly for 1) seeing how far into a file we must lseek to data, given
  1140.  * that we have a sparse file, and 2) determining the "real size" of the
  1141.  * file, i.e., the number of bytes in the sparse file that are data, as
  1142.  * opposed to the zeros we are trying to skip.
  1143.  */
  1144. where_is_data (from, to, buffer)
  1145.      int *from, *to;
  1146.      char *buffer;
  1147. {
  1148.   register int i = 0;
  1149.   register int save_to = *to;
  1150.   int amidst_data = 0;
  1151.  
  1152.  
  1153.   while (!buffer[i])
  1154.     i++;
  1155.   *from = i;
  1156.  
  1157.   if (*from < 16)        /* don't bother */
  1158.     *from = 0;
  1159.   /* keep going to make sure there isn't more real
  1160.        data in this record */
  1161.   while (i < RECORDSIZE)
  1162.     {
  1163.       if (!buffer[i])
  1164.     {
  1165.       if (amidst_data)
  1166.         {
  1167.           save_to = i;
  1168.           amidst_data = 0;
  1169.         }
  1170.       i++;
  1171.     }
  1172.       else if (buffer[i])
  1173.     {
  1174.       if (!amidst_data)
  1175.         amidst_data = 1;
  1176.       i++;
  1177.     }
  1178.     }
  1179.   if (i == RECORDSIZE)
  1180.     *to = i;
  1181.   else
  1182.     *to = save_to;
  1183.  
  1184. }
  1185.  
  1186. #endif
  1187.  
  1188. /* Note that this routine is only called if zero_record returned true */
  1189. #if 0                /* But we actually don't need it at all. */
  1190. where_is_data (from, to, buffer)
  1191.      int *from, *to;
  1192.      char *buffer;
  1193. {
  1194.   char *fp, *tp;
  1195.  
  1196.   for (fp = buffer; !*fp; fp++)
  1197.     ;
  1198.   for (tp = buffer + RECORDSIZE - 1; !*tp; tp--)
  1199.     ;
  1200.   *from = fp - buffer;
  1201.   *to = tp - buffer + 1;
  1202. }
  1203.  
  1204. #endif
  1205.  
  1206.  
  1207.  
  1208. /*
  1209.  * Takes a recordful of data and basically cruises through it to see if
  1210.  * it's made *entirely* of zeros, returning a 0 the instant it finds
  1211.  * something that is a non-zero, i.e., useful data.
  1212.  */
  1213. int
  1214. zero_record (buffer)
  1215.      char *buffer;
  1216. {
  1217.   register int i;
  1218.  
  1219.   for (i = 0; i < RECORDSIZE; i++)
  1220.     if (buffer[i] != '\000')
  1221.       return 0;
  1222.   return 1;
  1223. }
  1224.  
  1225. void
  1226. find_new_file_size (filesize, highest_index)
  1227.      int *filesize;
  1228.      int highest_index;
  1229. {
  1230.   register int i;
  1231.  
  1232.   *filesize = 0;
  1233.   for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
  1234.     *filesize += sparsearray[i].numbytes;
  1235. }
  1236.  
  1237. /*
  1238.  * Make a header block for the file  name  whose stat info is  st .
  1239.  * Return header pointer for success, NULL if the name is too long.
  1240.  */
  1241. union record *
  1242. start_header (name, st)
  1243.      char *name;
  1244.      register struct stat *st;
  1245. {
  1246.   register union record *header;
  1247.  
  1248.   if (strlen (name) >= NAMSIZ)
  1249.     write_long (name, LF_LONGNAME);
  1250.  
  1251.   header = (union record *) findrec ();
  1252.   bzero (header->charptr, sizeof (*header));    /* XXX speed up */
  1253.  
  1254.   /*
  1255.      * Check the file name and put it in the record.
  1256.      */
  1257.   if (!f_absolute_paths)
  1258.     {
  1259.       static int warned_once = 0;
  1260. #ifdef __MSDOS__
  1261.       if (name[1] == ':')
  1262.     {
  1263.       name += 2;
  1264.       if (!warned_once++)
  1265.         msg ("Removing drive spec from names in the archive");
  1266.     }
  1267. #endif
  1268.       while ('/' == *name)
  1269.     {
  1270.       name++;        /* Force relative path */
  1271.       if (!warned_once++)
  1272.         msg ("Removing leading / from absolute path names in the archive.");
  1273.     }
  1274.     }
  1275.   current_file_name = name;
  1276.   strncpy (header->header.arch_name, name, NAMSIZ);
  1277.   header->header.arch_name[NAMSIZ - 1] = '\0';
  1278.  
  1279.   to_oct ((long) (f_oldarch ? (st->st_mode & 07777) : st->st_mode),
  1280.       8, header->header.mode);
  1281.   to_oct ((long) st->st_uid, 8, header->header.uid);
  1282.   to_oct ((long) st->st_gid, 8, header->header.gid);
  1283.   to_oct ((long) st->st_size, 1 + 12, header->header.size);
  1284.   to_oct ((long) st->st_mtime, 1 + 12, header->header.mtime);
  1285.   /* header->header.linkflag is left as null */
  1286.   if (f_gnudump)
  1287.     {
  1288.       to_oct ((long) st->st_atime, 1 + 12, header->header.atime);
  1289.       to_oct ((long) st->st_ctime, 1 + 12, header->header.ctime);
  1290.     }
  1291.  
  1292. #ifndef NONAMES
  1293.   /* Fill in new Unix Standard fields if desired. */
  1294.   if (f_standard)
  1295.     {
  1296.       header->header.linkflag = LF_NORMAL;    /* New default */
  1297.       strcpy (header->header.magic, TMAGIC);    /* Mark as Unix Std */
  1298.       finduname (header->header.uname, st->st_uid);
  1299.       findgname (header->header.gname, st->st_gid);
  1300.     }
  1301. #endif
  1302.   return header;
  1303. }
  1304.  
  1305. /*
  1306.  * Finish off a filled-in header block and write it out.
  1307.  * We also print the file name and/or full info if verbose is on.
  1308.  */
  1309. void
  1310. finish_header (header)
  1311.      register union record *header;
  1312. {
  1313.   register int i, sum;
  1314.   register char *p;
  1315.  
  1316.   bcopy (CHKBLANKS, header->header.chksum, sizeof (header->header.chksum));
  1317.  
  1318.   sum = 0;
  1319.   p = header->charptr;
  1320.   for (i = sizeof (*header); --i >= 0;)
  1321.     {
  1322.       /*
  1323.          * We can't use unsigned char here because of old compilers,
  1324.          * e.g. V7.
  1325.          */
  1326.       sum += 0xFF & *p++;
  1327.     }
  1328.  
  1329.   /*
  1330.      * Fill in the checksum field.  It's formatted differently
  1331.      * from the other fields:  it has [6] digits, a null, then a
  1332.      * space -- rather than digits, a space, then a null.
  1333.      * We use to_oct then write the null in over to_oct's space.
  1334.      * The final space is already there, from checksumming, and
  1335.      * to_oct doesn't modify it.
  1336.      *
  1337.      * This is a fast way to do:
  1338.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1339.      */
  1340.   to_oct ((long) sum, 8, header->header.chksum);
  1341.   header->header.chksum[6] = '\0';    /* Zap the space */
  1342.  
  1343.   userec (header);
  1344.  
  1345.   if (f_verbose)
  1346.     {
  1347.       extern union record *head;/* Points to current tape header */
  1348.       extern int head_standard;    /* Tape header is in ANSI format */
  1349.  
  1350.       /* These globals are parameters to print_header, sigh */
  1351.       head = header;
  1352.       /* hstat is already set up */
  1353.       head_standard = f_standard;
  1354.       print_header ();
  1355.     }
  1356.  
  1357.   return;
  1358. }
  1359.  
  1360.  
  1361. /*
  1362.  * Quick and dirty octal conversion.
  1363.  * Converts long "value" into a "digs"-digit field at "where",
  1364.  * including a trailing space and room for a null.  "digs"==3 means
  1365.  * 1 digit, a space, and room for a null.
  1366.  *
  1367.  * We assume the trailing null is already there and don't fill it in.
  1368.  * This fact is used by start_header and finish_header, so don't change it!
  1369.  *
  1370.  * This should be equivalent to:
  1371.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1372.  * except that sprintf fills in the trailing null and we don't.
  1373.  */
  1374. void
  1375. to_oct (value, digs, where)
  1376.      register long value;
  1377.      register int digs;
  1378.      register char *where;
  1379. {
  1380.  
  1381.   --digs;            /* Trailing null slot is left alone */
  1382.   where[--digs] = ' ';        /* Put in the space, though */
  1383.  
  1384.   /* Produce the digits -- at least one */
  1385.   do
  1386.     {
  1387.       where[--digs] = '0' + (char) (value & 7);    /* one octal digit */
  1388.       value >>= 3;
  1389.     }
  1390.   while (digs > 0 && value != 0);
  1391.  
  1392.   /* Leading spaces, if necessary */
  1393.   while (digs > 0)
  1394.     where[--digs] = ' ';
  1395.  
  1396. }
  1397.  
  1398.  
  1399. /*
  1400.  * Write the EOT record(s).
  1401.  * We actually zero at least one record, through the end of the block.
  1402.  * Old tar writes garbage after two zeroed records -- and PDtar used to.
  1403.  */
  1404. void
  1405. write_eot ()
  1406. {
  1407.   union record *p;
  1408.   int bufsize;
  1409.  
  1410.   p = findrec ();
  1411.   if (p)
  1412.     {
  1413.       bufsize = endofrecs ()->charptr - p->charptr;
  1414.       bzero (p->charptr, bufsize);
  1415.       userec (p);
  1416.     }
  1417. }
  1418.  
  1419. /* Write a LF_LONGLINK or LF_LONGNAME record. */
  1420. void
  1421. write_long (p, type)
  1422.      char *p;
  1423.      char type;
  1424. {
  1425.   int size = strlen (p) + 1;
  1426.   int bufsize;
  1427.   union record *header;
  1428.   struct stat foo;
  1429.  
  1430.  
  1431.   bzero (&foo, sizeof foo);
  1432.   foo.st_size = size;
  1433.  
  1434.   header = start_header ("././@LongLink", &foo);
  1435.   header->header.linkflag = type;
  1436.   finish_header (header);
  1437.  
  1438.   header = findrec ();
  1439.  
  1440.   bufsize = endofrecs ()->charptr - header->charptr;
  1441.  
  1442.   while (bufsize < size)
  1443.     {
  1444.       bcopy (p, header->charptr, bufsize);
  1445.       p += bufsize;
  1446.       size -= bufsize;
  1447.       userec (header + (bufsize - 1) / RECORDSIZE);
  1448.       header = findrec ();
  1449.       bufsize = endofrecs ()->charptr - header->charptr;
  1450.     }
  1451.   bcopy (p, header->charptr, size);
  1452.   bzero (header->charptr + size, bufsize - size);
  1453.   userec (header + (size - 1) / RECORDSIZE);
  1454. }
  1455.